#include "key.h"

/**
 * @brief 初始化按键
 * @param handle 按键句柄指针
 * @param pin 按键引脚
 */
void key_init(KeyHandle* handle, uint8_t pin) {
  if (handle == NULL) return;
  
  // 初始化按键结构体
  handle->pin = pin;
  handle->swichKeyState = KEY_STATE_IDLE;
  handle->swichKeyPressTime = 0;
  handle->swichKeyShortPressCallback = NULL;
  handle->swichKeyLongPressCallback = NULL;
  
  // 设置引脚为输入上拉模式
  pinMode(pin, INPUT_PULLUP);
}

/**
 * @brief 按键状态机处理函数
 * @param handle 按键句柄指针
 * @details 该函数需要在主循环中周期性调用，用于检测按键状态变化并触发相应回调
 */
void key_state_machine(KeyHandle* handle) {
  if (handle == NULL) return;
  
  // 读取当前按键状态（低电平表示按下）
  bool keyPressed = (digitalRead(handle->pin) == LOW);
  unsigned long currentTime = millis();
  
  // 按键状态机
  switch (handle->swichKeyState) {
    case KEY_STATE_IDLE:
      if (keyPressed) {
        // 按键按下，记录时间并进入去抖动
        handle->swichKeyPressTime = currentTime;
        handle->swichKeyState = KEY_STATE_SHORT_PRESS;
      }
      break;
      
    case KEY_STATE_SHORT_PRESS:
      if (!keyPressed) {
        // 按键释放
        if ((currentTime - handle->swichKeyPressTime) >= DEBOUNCE_TIME) {
          // 去抖动时间已过，确认为短按
          if (handle->swichKeyShortPressCallback != NULL) {
            handle->swichKeyShortPressCallback(); // 触发短按回调
          }
        }
        // 无论如何都返回空闲状态
        handle->swichKeyState = KEY_STATE_IDLE;
      } else if ((currentTime - handle->swichKeyPressTime) >= LONG_PRESS_TIME) {
        // 按键持续按下超过长按时间
        handle->swichKeyState = KEY_STATE_LONG_PRESS;
        if (handle->swichKeyLongPressCallback != NULL) {
          handle->swichKeyLongPressCallback(); // 触发长按回调
        }
      }
      break;
      
    case KEY_STATE_LONG_PRESS:
      if (!keyPressed) {
        // 长按后释放，返回空闲状态
        handle->swichKeyState = KEY_STATE_IDLE;
      }
      break;
      
    default:
      // 异常状态，重置为空闲
      handle->swichKeyState = KEY_STATE_IDLE;
      break;
  }
}

/**
 * @brief 注册短按事件回调函数
 * @param handle 按键句柄指针
 * @param callback 回调函数指针
 */
void key_short_press_event_register(KeyHandle* handle, KeyEventCallback callback) {
  if (handle != NULL) {
    handle->swichKeyShortPressCallback = callback;
  }
}

/**
 * @brief 注册长按事件回调函数
 * @param handle 按键句柄指针
 * @param callback 回调函数指针
 */
void key_long_press_event_register(KeyHandle* handle, KeyEventCallback callback) {
  if (handle != NULL) {
    handle->swichKeyLongPressCallback = callback;
  }
}